package service

import (
	"github.com/tealeg/xlsx"
	"strconv"
	"time"
	"zimuzu_cvn_web_api/config"
	"zimuzu_cvn_web_api/model"
	"zimuzu_cvn_web_api/pkg/e"
	"zimuzu_cvn_web_api/pkg/errno"
	"zimuzu_cvn_web_api/pkg/util"
)

func GetCvntYtaPrice(Uid int64) (res model.CoinPriceShow, err error) {

	// 获取用户的钱包可用余额
	userAmount, err := model.GetCvnAmount(config.C.DB.DB, Uid)
	if err != nil {
		return res, err
	}

	baseUrl := "https://exchange-open-api.coineal.com/open/api/get_ticker?symbol="
	var cvnPriceRes, ytaPriceRes model.CoinPriceResponse
	err = e.HttpGet(baseUrl+"cvntusdt", &cvnPriceRes)
	if err != nil {
		return res, err
	}
	err = e.HttpGet(baseUrl+"ytausdt", &ytaPriceRes)
	if err != nil {
		return res, err
	}
	if cvnPriceRes.Code == 0 && ytaPriceRes.Code == 0 {
		rate := e.Decimal(cvnPriceRes.Data.Last/ytaPriceRes.Data.Last*e.YtaRechargeCvntRate, 4)
		res.CVNT = cvnPriceRes.Data.Last
		res.YTA = ytaPriceRes.Data.Last
		res.Balance = userAmount.Balance
		res.Rate = rate
		res.ToYta = e.Decimal(rate*userAmount.Balance, 4)
		return res, nil
	}

	return res, errno.RecordError
}

// 兑换YTA
func RechargeYtaUseCVNT(Uid int64, Cvn float64) (err error) {

	userPrice, err := GetCvntYtaPrice(Uid)
	if err != nil {
		return err
	}

	if Cvn > userPrice.Balance {
		return errno.WalletNotEnoughERR
	}

	// 用户YTA地址
	address, err := model.GetYtaAddress(Uid)
	if err != nil {
		return errno.ErrYtaAddress
	}
	if address.Status == 0 {
		return errno.ErrYtaApplyAddress
	}

	// 开启事务
	conn, err := config.C.DB.DB.Beginx()
	if err != nil {
		return err
	}

	var addRecharge model.YtaRechargeLogResponse
	addRecharge.Uid = Uid
	addRecharge.Cvn = Cvn
	addRecharge.Address = address.Address
	addRecharge.Yta = e.Decimal(userPrice.Rate*Cvn, 4)
	addRecharge.CvnPrice = userPrice.CVNT
	addRecharge.YtaPrice = userPrice.YTA
	logId, err := model.AddYtaRechargeLog(conn, addRecharge)
	if err != nil {
		conn.Rollback()
		return err
	}

	//修改amount,插入cvn流水
	updateAmountData := UpdateCvnAmountParams{
		Uid:          Uid,
		Amount:       -Cvn,
		FrozenAmount: Cvn,
		Source:       model.LogSourceSystemRechargeYTA,
		RelateId:     strconv.FormatInt(logId, 10),
		RelateTable:  "mg_yta_recharge",
	}
	_, err = UpdateCvnAmountBalance(conn, updateAmountData)
	if err != nil {
		conn.Rollback()
		return err
	}

	conn.Commit()
	return nil
}

// 获取Yta兑换记录
func GetAdminYtaRechargeLog(TargetUid int, Page, per, Status int, Start, End string) (res model.List, err error) {
	StartLimit := (Page - 1) * per
	db := config.C.DB.DB
	// 列表数据
	list, err := model.GetAdminYtaRechargeLogData(db, TargetUid, Status, StartLimit, per, Start, End)
	if err != nil {
		return res, err
	}
	// 总记录数
	countItem, err := model.GetAdminYtaRechargeLogCount(db, TargetUid, Status, Start, End)
	if err != nil {
		return res, err
	}
	// 组装结果集合
	countPage := e.ListPage(countItem, per)
	res.CountItem = countItem
	res.CountPage = countPage
	res.List = list
	return res, nil
}

// 地址列表
func GetAdminYtaAddressList(TargetUid int, Page, per, Status int, Start, End string) (res model.List, err error) {

	db := config.C.DB.DB
	StartLimit := (Page - 1) * per
	// 列表数据
	list, err := model.GetAdminYtaAddressListData(db, TargetUid, Status, StartLimit, per, Start, End)
	if err != nil {
		return res, err
	}
	// 总记录数
	countItem, err := model.GetAdminYtaAddressListCount(db, TargetUid, Status, Start, End)
	if err != nil {
		return res, err
	}
	// 组装结果集合
	countPage := e.ListPage(countItem, per)
	res.CountItem = countItem
	res.CountPage = countPage
	res.List = list
	return res, nil
}

// 单个修改兑换状态
func SingleUpdateAdminYtaRecharge(Id int64, Status int) (err error) {

	log, err := model.GetYtaRechargeLogById(Id)
	if err != nil {
		return err
	}
	if log.Status == Status {
		return nil
	}
	if log.Status > 0 {
		return errno.ErrYtaRechargeStatus
	}
	// 开启事务
	conn, err := config.C.DB.DB.Beginx()
	if err != nil {
		return err
	}

	// 更新状态
	err = model.UpdateYtaRechargeLog(conn, Id, Status)
	if err != nil {
		conn.Rollback()
		return err
	}

	if Status == 10 {
		// 如果是审核通过则扣除不可用余额
		//修改amount,插入cvn流水
		updateAmountData := UpdateCvnAmountParams{
			Uid:          log.Uid,
			FrozenAmount: -log.Cvn,
		}
		_, err = UpdateCvnAmountBalance(conn, updateAmountData)
	} else if Status == 20 {
		// 如果是退回，退回用的不可用余额到用户的可用余额
		//修改amount,插入cvn流水
		updateAmountData := UpdateCvnAmountParams{
			Uid:          log.Uid,
			FrozenAmount: -log.Cvn,
			Amount:       log.Cvn,
			Source:       model.LogSourceRechargeYTABack,
		}
		_, err = UpdateCvnAmountBalance(conn, updateAmountData)
	} else {
		return errno.ErrYtaRechargeStatus
	}

	if err != nil {
		e.Log("info", "修改兑换状态失败,", "数据回滚：", err.Error())
		conn.Rollback()
		return err
	}

	conn.Commit()
	return nil
}

// 导出Excel
func DownExcelWithYtaAddressList(TargetUid int, Status int, Start, End string) (downUrl string, err error) {

	var res []model.DownExcelYtaAddressList
	db := config.C.DB.DB
	tempData, err := model.GetAdminYtaAddressListDataNoPage(db, TargetUid, Status, Start, End)
	if err != nil {
		return downUrl, err
	}
	var ttData model.DownExcelYtaAddressList
	for _, k := range tempData {
		ttData.Uid = k.Uid
		ttData.CreateTime = k.CreateTime.Format(e.TimeFormatS)
		ttData.Address = k.Address
		switch k.Status {
		case 0:
			ttData.Status = "未审核"
			break
		case 1:
			ttData.Status = "有效地址"
			break
		case 2:
			ttData.Status = "无效地址"
			break
		default:
			ttData.Status = "异常数据"
			break
		}
		res = append(res, ttData)
	}
	t := make([]string, 0)
	t = append(t, "时间")
	t = append(t, "Uid")
	t = append(t, "地址")
	t = append(t, "状态")
	file := xlsx.NewFile()
	sheet, err := file.AddSheet("sheet")
	if err != nil {
		return downUrl, err
	}
	titleRow := sheet.AddRow()
	xlsRow := util.NewRow(titleRow, t)
	err = xlsRow.SetRowTitle()
	if err != nil {
		return downUrl, err
	}
	for _, k := range res {
		uidStr := strconv.FormatInt(k.Uid, 10)
		currentRow := sheet.AddRow()
		tmp := make([]string, 0)
		tmp = append(tmp, k.CreateTime)
		tmp = append(tmp, uidStr)
		tmp = append(tmp, k.Address)
		tmp = append(tmp, k.Status)
		xlsRow := util.NewRow(currentRow, tmp)
		err := xlsRow.GenerateRow()
		if err != nil {
			return downUrl, err
		}
	}
	fileName := strconv.FormatInt(time.Now().Unix(), 10)
	fileNameStr := "yta_address_" + fileName + ".xlsx"
	localPath, showPtah, err := getYtaExcelDir()
	if err != nil {
		return downUrl, err
	}
	downUrl = localPath + fileNameStr
	err = file.Save(downUrl)
	if err != nil {
		return fileNameStr, err
	}
	returnFile := showPtah + fileNameStr
	return returnFile, nil
}

// 导出Excel
func DownExcelWithYtaRechargeList(TargetUid int, Status int, Start, End string) (downUrl string, err error) {

	db := config.C.DB.DB
	tempData, err := model.GetAdminYtaRechargeLogDataNoPage(db, TargetUid, Status, Start, End)
	if err != nil {
		return downUrl, err
	}
	var res []model.DownExcelYtaRechargeLog
	var ttData model.DownExcelYtaRechargeLog
	for _, k := range tempData {
		ttData.Uid = k.Uid
		ttData.Address = k.Address
		ttData.Cvn = k.Cvn
		ttData.Yta = k.Yta
		ttData.CvnPrice = k.CvnPrice
		ttData.YtaPrice = k.YtaPrice
		ttData.CreateTime = k.CreateTime.Format(e.TimeFormatS)
		switch k.Status {
		case 0:
			ttData.Status = "待发放"
			break
		case 10:
			ttData.Status = "已发放"
			break
		case 20:
			ttData.Status = "已驳回"
			break
		case 30:
			ttData.Status = "已取消"
			break
		default:
			ttData.Status = "异常数据"
			break
		}
		res = append(res, ttData)
	}
	t := make([]string, 0)
	t = append(t, "时间")
	t = append(t, "Uid")
	t = append(t, "地址")
	t = append(t, "CVN实时币价")
	t = append(t, "YTA实时币价")
	t = append(t, "兑换比")
	t = append(t, "缴纳CVNT")
	t = append(t, "获得YTA")
	t = append(t, "目前状态")
	file := xlsx.NewFile()
	sheet, err := file.AddSheet("sheet")
	if err != nil {
		return downUrl, err
	}
	titleRow := sheet.AddRow()
	xlsRow := util.NewRow(titleRow, t)
	err = xlsRow.SetRowTitle()
	if err != nil {
		return downUrl, err
	}
	for _, k := range res {
		uidStr := strconv.FormatInt(k.Uid, 10)
		rate := strconv.FormatFloat(e.Decimal(k.CvnPrice/k.YtaPrice, 4), 'f', -1, 64)
		cvn := strconv.FormatFloat(e.Decimal(k.Cvn, 4), 'f', -1, 64)
		yta := strconv.FormatFloat(e.Decimal(k.Yta, 4), 'f', -1, 64)
		cvnPrice := strconv.FormatFloat(e.Decimal(k.CvnPrice, 8), 'f', -1, 64)
		ytaPrice := strconv.FormatFloat(e.Decimal(k.YtaPrice, 8), 'f', -1, 64)
		currentRow := sheet.AddRow()
		tmp := make([]string, 0)
		tmp = append(tmp, k.CreateTime)
		tmp = append(tmp, uidStr)
		tmp = append(tmp, k.Address)
		tmp = append(tmp, cvnPrice)
		tmp = append(tmp, ytaPrice)
		tmp = append(tmp, rate)
		tmp = append(tmp, cvn)
		tmp = append(tmp, yta)
		tmp = append(tmp, k.Status)
		xlsRow := util.NewRow(currentRow, tmp)
		err := xlsRow.GenerateRow()
		if err != nil {
			return downUrl, err
		}
	}
	fileName := strconv.FormatInt(time.Now().Unix(), 10)
	fileNameStr := "yta_recharge_" + fileName + ".xlsx"
	path, showPtah, err := getYtaExcelDir()
	if err != nil {
		return downUrl, err
	}
	downUrl = path + fileNameStr
	err = file.Save(downUrl)
	if err != nil {
		return fileNameStr, err
	}
	returnFile := showPtah + fileNameStr
	return returnFile, nil
}

func getYtaExcelDir() (localPtah, showPtah string, err error) {
	showPtah = time.Now().Format(e.TimeFormatD) + "/"
	localPtah = "./" + e.ExcelResourceLocal + showPtah
	if bo, _ := e.MakeDir(localPtah); bo {
		e.Log("info", "path=", localPtah)
		return localPtah, showPtah, nil
	}
	return localPtah, showPtah, errno.DbDataError
}
